home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
lisp
/
eulisp
/
mpfeel.lha
/
MPFeel
/
listops.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-10-06
|
8KB
|
360 lines
/* ******************************************************************** */
/* listops.c Copyright (C) Codemist and University of Bath 1989 */
/* */
/* further list operations */
/* ******************************************************************** */
/*
* $Id: listops.c,v 1.5 1992/01/07 22:15:36 pab Exp $
*
* $Log: listops.c,v $
* Revision 1.5 1992/01/07 22:15:36 pab
* ncc compatable, plus backtrace
*
* Revision 1.4 1991/12/22 15:14:15 pab
* Xmas revision
*
* Revision 1.3 1991/09/22 19:14:35 pab
* Fixed obvious bugs
*
* Revision 1.2 1991/09/11 12:07:20 pab
* 11/9/91 First Alpha release of modified system
*
* Revision 1.1 1991/08/12 16:49:43 pab
* Initial revision
*
* Revision 1.4 1991/02/13 18:22:07 kjp
* Pass.
*
*/
/*
* Change Log:
* Version 1, March 1990 (Compiler rationalisation)
*/
#include "defs.h"
#include "structs.h"
#include "funcalls.h"
#include "error.h"
#include "global.h"
#include "modboot.h"
#include "symboot.h"
#include "calls.h"
#include "modules.h"
#include "ngenerics.h"
LispObject flat_list_copy(LispObject *);
EUFUN_1( Fn_null, form)
{
return (form==nil?lisptrue:nil);
}
EUFUN_CLOSE
/* Destructive append */
EUFUN_2( Fn_nconc, form1, form2)
{
LispObject p = form1;
if (!is_cons(form1)) return(form2);
while (CDR(p)!=nil) p = CDR(p);
CDR(p) = form2;
return form1;
}
EUFUN_CLOSE
EUFUN_2( Fn_append, l1, l2)
{
LispObject endptr,walker,val;
if (!is_cons(l1)) return(l2);
/* reasonable append */
val = EUCALL_2(Fn_cons,CAR(l1),nil);
STACK_TMP(val);
endptr = val;
walker = CDR(ARG_0(stackbase)/*l1*/);
while (is_cons(walker))
{
LispObject xx;
STACK_TMP(endptr);
STACK_TMP(CDR(walker));
xx = EUCALL_2(Fn_cons, CAR(walker), nil);
UNSTACK_TMP(walker);
UNSTACK_TMP(endptr);
CDR(endptr)=xx;
endptr=CDR(endptr);
}
CDR(endptr) = ARG_1(stackbase)/*l2*/;
UNSTACK_TMP(val);
return(val);
}
EUFUN_CLOSE
/* Simple predicate for NULL */
EUFUN_1( Fn_lastpair, form)
{
while (!is_cons(form))
form = CallError(stacktop,"Not a list in last-pair",form,CONTINUABLE);
while (CDR(form)!=nil) form = CDR(form);
return form;
}
EUFUN_CLOSE
EUFUN_1( Fn_nreverse, form)
{
LispObject x=nil;
while (form!=nil) {
LispObject y = CDR(form);
CDR(form) = x;
x = form;
form = y;
}
return x;
}
EUFUN_CLOSE
EUFUN_3( Fn_assoc, obj, list, fn)
{
while (list!=nil) {
LispObject xx;
EUCALLSET_3(xx,apply2,ARG_2(stackbase),ARG_0(stackbase),CAR(CAR(list)));
if (xx != nil) {
list=ARG_1(stackbase);
return CAR(list);
}
list = ARG_1(stackbase);
list = CDR(list);
ARG_1(stackbase) = list;
}
return nil;
}
EUFUN_CLOSE
EUFUN_3( Fn_member, obj, list, fn)
{
while (list!=nil) {
if (EUCALL_3(apply2,ARG_2(stackbase),ARG_0(stackbase),CAR(list)) != nil) {
return ARG_1(stackbase);
}
list = ARG_1(stackbase);
list = CDR(list);
ARG_1(stackbase) = list;
}
return nil;
}
EUFUN_CLOSE
EUFUN_2( Fn_memq, obj, list)
{
if (!is_cons(list) && list != nil)
CallError(stacktop,"memq: non-lists passed",list,NONCONTINUABLE);
while (is_cons(list)) {
if (obj == CAR(list))
return(lisptrue);
else
list = CDR(list);
}
return(nil);
}
EUFUN_CLOSE
/* ******************************************************************** */
/* Lisp Mappers */
/* ******************************************************************** */
static LispObject mapcar_apply_args(LispObject *stackbase, LispObject set)
{
LispObject walker,res,ptr;
LispObject *stacktop=stackbase+1;
ARG_0(stackbase)=nil;
res = nil; ptr = nil;
walker = set;
while (is_cons(walker))
{
if (!is_cons(CAR(walker)))
return(nil);
STACK_TMP(CDR(walker));
if (ptr == nil)
{
EUCALLSET_2(res, Fn_cons,CAR(CAR(walker)),nil);
ARG_0(stackbase)=res;
ptr = res;
}
else
{
LispObject xx;
STACK_TMP(ptr);
EUCALLSET_2(xx, Fn_cons, CAR(CAR(walker)),nil);
UNSTACK_TMP(ptr);
CDR(ptr) = xx;
ptr = CDR(ptr);
}
UNSTACK_TMP(walker);
}
res=ARG_0(stackbase);
return(res);
}
static LispObject mapcar_advance_lists(LispObject set)
{
LispObject walker = set;
while (is_cons(walker)) {
CAR(walker) = CDR(CAR(walker));
walker = CDR(walker);
}
return(set);
}
EUFUN_3( Fn_mapcar, fn, l1, lists)
{
LispObject flat_list_copy(LispObject *);
if (!is_cons(l1) && l1 != nil)
CallError(stacktop,"mapcar: not a list",l1,NONCONTINUABLE);
ARG_3(stackbase)=nil;
stacktop++;
{
LispObject set,args;
LispObject res,ptr,val;
/* More general... */
EUCALLSET_1(set, flat_list_copy, lists);
EUCALLSET_2(set, Fn_cons,ARG_1(stackbase),set);
res = nil; ptr = nil;
while (TRUE)
{
/* Construct args to apply... */
STACK_TMP(set);
STACK_TMP(ptr);
if ((args = mapcar_apply_args(stacktop,set)) == nil)
{
res=ARG_3(stackbase);
return(res);
}
UNSTACK_TMP(ptr);
STACK_TMP(ptr);
EUCALLSET_2(val,module_mv_apply_1,ARG_0(stackbase),args);
UNSTACK_TMP(ptr);
if (ptr == nil)
{
EUCALLSET_2(res, Fn_cons,val,nil);
ARG_3(stackbase)=res;
ptr = res;
}
else
{
LispObject xx;
STACK_TMP(ptr);
EUCALLSET_2(xx, Fn_cons, val,nil);
UNSTACK_TMP(ptr);
CDR(ptr) = xx;
ptr = CDR(ptr);
}
UNSTACK_TMP(set);
mapcar_advance_lists(set);
}
}
return(nil);
}
EUFUN_CLOSE
EUFUN_3( Fn_mapc, fn, l1, lists)
{
if (!is_cons(l1) && l1 != nil)
CallError(stacktop,"mapc: not a list",l1,NONCONTINUABLE);
if (FALSE) {
;
}
else {
LispObject set,args;
/* More general... */
EUCALLSET_1(set,flat_list_copy,lists);
EUCALLSET_2(set, Fn_cons,ARG_1(stackbase),set);
while (TRUE) {
LispObject dummy;
/* Construct args to apply... */
STACK_TMP(set);
if ((args = mapcar_apply_args(stacktop,set)) == nil) {
return(nil);
}
UNSTACK_TMP(set);
STACK_TMP(set);
EUCALL_2(module_mv_apply_1,ARG_0(stackbase),args);
UNSTACK_TMP(set);
mapcar_advance_lists(set);
}
}
return(nil);
}
EUFUN_CLOSE
EUFUN_1( flat_list_copy, list)
{
LispObject xx;
if (!is_cons(list)) return(nil);
EUCALLSET_1(xx, flat_list_copy, CDR(list));
return(EUCALL_2(Fn_cons, CAR(ARG_0(stackbase)),xx));
}
EUFUN_CLOSE
/*
* Initialise the module...
*/
#define LISTOPS_ENTRIES 11
MODULE Module_listops;
LispObject Module_listops_values[LISTOPS_ENTRIES];
void initialise_listops(LispObject *stacktop)
{
open_module(stacktop,
&Module_listops,
Module_listops_values,
"list-operators",
LISTOPS_ENTRIES);
(void) make_module_function(stacktop,"memq",Fn_memq,2);
(void) make_module_function(stacktop,"append",Fn_append,2);
(void) make_module_function(stacktop,"copy-list",flat_list_copy,1);
(void) make_module_function(stacktop,"null",Fn_null,1);
(void) make_module_function(stacktop,"nconc",Fn_nconc,2);
(void) make_module_function(stacktop,"last-pair",Fn_lastpair,1);
(void) make_module_function(stacktop,"nreverse",Fn_nreverse,1);
(void) make_module_function(stacktop,"assoc",Fn_assoc,3);
(void) make_module_function(stacktop,"member",Fn_member,3);
(void) make_module_function(stacktop,"mapcar",Fn_mapcar,-3);
(void) make_module_function(stacktop,"mapc",Fn_mapc,-3);
close_module();
}